package org.zjvis.datascience.service;

import cn.hutool.crypto.digest.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.zjvis.datascience.common.constant.UserConstant;
import org.zjvis.datascience.common.dto.user.UserDTO;
import org.zjvis.datascience.common.dto.user.UserFeedbackDTO;
import org.zjvis.datascience.common.exception.BaseErrorCode;
import org.zjvis.datascience.common.exception.DataScienceException;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.util.RedisUtil;
import org.zjvis.datascience.common.vo.user.UserModifyPasswordVO;
import org.zjvis.datascience.service.mapper.UserConfigMapper;
import org.zjvis.datascience.service.mapper.UserFeedbackMapper;
import org.zjvis.datascience.service.mapper.UserMapper;

import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * @description User 用户 Service
 * @date 2021-12-26
 */
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserFeedbackMapper userFeedbackMapper;

    @Autowired
    private UserConfigMapper userConfigMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private PasswordService passwordService;

    public Long save(UserDTO user) {
        encryptPassword(user);
        userMapper.insertSelective(user);
        //生成一个默认配置
        userConfigMapper.insert(user.getId());
        return user.getId();
    }

    /**
     * 检查手机号是否已经注册
     *
     * @param key
     * @return boolean
     */
    public boolean checkUserIsExist(String key) {
        UserDTO userRecord = userMapper.findByKey(key);
        return (userRecord != null);
    }

    /**
     * 校验两次密码是否相同
     *
     * @param user
     * @return boolean
     */
    public boolean isEqual(UserModifyPasswordVO user) {
        if (!user.getPassword1().equals(user.getPassword2())) {
            throw new DataScienceException(BaseErrorCode.USER_PASSWORD_NOT_EQUAL);
        }
        return true;
    }

    /**
     * 操作数据库修改密码
     *
     * @param user
     */
    public boolean updatePassword(UserModifyPasswordVO user) {
        UserDTO userRecord = userMapper.findByKey(user.getPhone());
        if(BCrypt.checkpw(user.getPassword1(), userRecord.getPassword())) {
            throw new DataScienceException(BaseErrorCode.USER_PASSWORD_CANNOT_SAME);
        }
        String raw = passwordService.decryptPassword(user.getPassword1());
        user.setPassword(BCrypt.hashpw(raw));
        userMapper.updatePassword(user);
        userRecord = userMapper.findByKey(user.getPhone());
        if (userRecord == null) {
            throw new DataScienceException(BaseErrorCode.USER_USERNAME_OR_PASSWORD_ERROR);
        }
        String key = UserConstant.LOGIN_TIMES_PREFIX + userRecord.getName();
        if (redisUtil.get(key) != null) {
            redisUtil.del(key);
        }
        return true;
    }

    private void encryptPassword(UserDTO user) {
        String raw = passwordService.decryptPassword(user.getPassword());
        user.setPassword(BCrypt.hashpw(raw));
    }

    public boolean delete(Long id) {
        int count = userMapper.deleteByPrimaryKey(id);
        return count > 0;
    }


    public boolean update(UserDTO user) {
        checkAuth(user.getId());
        //禁止通过该接口修改密码用户名等关键信息，设置为null即无法修改！
        user.setName(null);
        user.setPassword(null);
        user.setStatus(null);

        try {
            userMapper.updateByPrimaryKeySelective(user);
        } catch (DuplicateKeyException e) {
            throw new DataScienceException(BaseErrorCode.USER_ALREADY_EXIST);
        }
        return true;
    }

    public boolean insertFeedback(UserFeedbackDTO user) {
        checkAuth(user.getId());
        user.setUserId(user.getId());
        userFeedbackMapper.insertUserFeedback(user);
        return true;
    }


    private void checkAuth(long id) {
        if (JwtUtil.getCurrentUserId() != id) {
            throw new DataScienceException(BaseErrorCode.UNAUTHORIZED);
        }
    }

    public boolean exist(long id) {
        return userMapper.selectByPrimaryKey(id) != null;
    }

    public void checkValidUser(long id) {
        if (exist(id)) {
            return;
        }
        throw new DataScienceException(BaseErrorCode.USER_USERNAME_OR_PASSWORD_ERROR);
    }

    public UserDTO checkValidUser2(long id) {
        UserDTO dto = userMapper.selectByPrimaryKey(id);
        if (dto != null) {
            return dto;
        }
        throw new DataScienceException(BaseErrorCode.USER_USERNAME_OR_PASSWORD_ERROR);
    }

    public UserDTO queryById(Long id) {
        //checkAuth(id);
        return userMapper.selectByPrimaryKey(id);
    }

    /**
     * 仅用作生成用户cookie
     *
     * @param name 用户名
     * @return
     */
    public UserDTO queryByName(String name) {
        UserDTO user = UserDTO.builder().name(name).build();
        List<UserDTO> users = userMapper.select(user);
        if (CollectionUtils.isEmpty(users)) {
            return null;
        }
        return users.get(0);
    }

    public List<UserDTO> queryBlurryByName(String name) {
        if (name != null) {
            name = name + "%";
        }
        List<UserDTO> users = userMapper.selectByName(name);
        if (CollectionUtils.isEmpty(users)) {
            return null;
        }
        return users;
    }

    public Set<String> queryPermissionByUserId(Long id) {
        return Collections.EMPTY_SET;
    }

    public List<UserDTO> listByIds(Set<Long> ids) {
        return userMapper.listByIds(ids);
    }

    /**
     * 修改用户guideStatus状态
     */
    public Boolean changeGuideStatus(Long id) {
        if (id == null || id <= 0) {
            throw new DataScienceException(BaseErrorCode.USER_USERNAME_OR_PASSWORD_ERROR);
        }
        userMapper.updateGuideStatus(id);
        return true;
    }

    public int checkGuideStatus(Long id) {
        if (id == null || id <= 0) {
            throw new DataScienceException(BaseErrorCode.USER_USERNAME_OR_PASSWORD_ERROR);
        }
        UserDTO user = userMapper.selectByPrimaryKey(id);
        return user.getGuideStatus();
    }

    public boolean phoneBind(UserDTO user, String phone) {
        user.setPhone(phone);
        userMapper.updatePhone(user);
        return true;
    }

    public boolean judgeNamePhone(String name, String phone) {
        if(name == null) {
            throw new DataScienceException(BaseErrorCode.USER_INFO_IS_NULL);
        }
        UserDTO userRecord = userMapper.findByKey(phone);
        // 平台支持手机号和名字登录的方式，用户输入的可能是名字也可能是手机号，一起判断
        if(userRecord.getName().equals(name) || userRecord.getPhone().equals(name)) {
            return true;
        }
        throw new DataScienceException(BaseErrorCode.USER_PHONE_NOT_CORRESPOND);
    }
}
